package homework.course;

import homework.course.role.Student;
import homework.course.role.Teacher;
import homework.util.observer.Observable;
import homework.util.observer.Observer;

public class Classroom implements Observer, Runnable {

    private volatile boolean ended = true;
    public final static int TICK = 2000;
    private int currentDuration = 0;
    private int duration;
    private Teacher teacher;
    private Student[] students;

    public Classroom(int duration, Teacher teacher, Student... students) {
        this.duration = duration * TICK;
        this.teacher = teacher;
        this.students = students;
        teacher.addObserver(this);
        for(Student std: students) {
            std.addObserver(this);
        }
    }

    public void begin() {
        ended = false;
    }

    public void end() {
        ended = true;
    }

    public boolean isEnded() {
        if(duration <= currentDuration)
            ended = true;
        return ended;
    }

    public void mainLoop() {
        begin();
        while(!isEnded()) {
            try {
                Thread.sleep(TICK);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            currentDuration += TICK;

            System.out.println("-------------------");
            int i = (int)Math.round(Math.random()*2);
            if(i == 0) {
                teacher.speak();
            } else if(i == 1) {
                teacher.pollAllStudents(students);
            } else if(i == 2) {
                teacher.askQuestion(students);
            } else {
                throw new IllegalStateException(String.valueOf(i));
            }
        }
        System.out.println("下课了");
    }

    private void notifyStudents(Object obj, String msg) {
        for(Student std: students)
            std.listen(obj, msg);
    }

    @Override
    public void run() {
        mainLoop();
    }

    @Override
    public void receive(Observable observable, Object obj) {
        if(observable == teacher) {
            if(obj == null) {
                printSystemMessage(teacher, "沉默了");
                notifyStudents(observable, null);
            } else {
                switch (((Message) obj).getType()) {
                    case WORDS:
                        printPersonMessage(teacher, obj);
                        notifyStudents(observable, obj.toString());
                        break;
                    case SYSTEM:
                        printSystemMessage(teacher, obj);
                        break;
                }
            }
        } else if(observable instanceof Student) {
            switch (((Message) obj).getType()) {
                case SYSTEM:
                    printSystemMessage(observable, obj);
                    break;
                case WORDS:
                    printPersonMessage(observable, obj);
                    notifyStudents(observable, obj.toString());
                    teacher.listen(observable, obj.toString());
                    break;
            }
        }
    }

    public void printSystemMessage(Object obj, Object msg) {
        if(obj instanceof Student) {
            Student student = (Student) obj;
            System.out.println(String.format("[%s %s] %s", student, student.getCurrentState(), msg));
        } else {
            System.out.println(String.format("[%s] %s", obj, msg));
        }
    }

    public void printPersonMessage(Object obj, Object msg) {
        System.out.println(String.format("%s说: %s", obj, msg));
    }
}
